#ifndef LspManagement_H
#define LspManagement_H

#include "simodo/lsp-client/LanguageClient.h"
#include "simodo/tp/ThreadPool.h"
#include "simodo/shell/document/DocumentAdaptor_interface.h"
#include "simodo/shell/access/LspStructures.h"
#include "simodo/shell/access/LspAccess_interface.h"
#include "Logger.h"

#include <QString>
#include <QObject>

#include <memory>
#include <set>

namespace shell = simodo::shell;

class MainWindow;

class LspManagement: public QObject, public shell::LspAccess_interface
{
    Q_OBJECT

    MainWindow *            _main_window;
    QString                 _path_to_client_setup_folder;

    Logger                  _log;

    std::map<QString,std::unique_ptr<simodo::lsp::LanguageClient>>  _servers;
    std::map<QString,std::pair<QString,QString>>                    _extension_to_language_and_server_name;

    simodo::tp::ThreadPool  _tp;

public:
    LspManagement(MainWindow * main_window);

    bool prepare();

    bool checkPath(const QString & path);

    void opened(const QString & path_to_file, const std::shared_ptr<shell::DocumentAdaptor_interface> doc);
    void closed(const QString & path_to_file);

public:
    // LspAccess_interface:
    virtual QString getLanguageId(const QString & path) override;
    virtual bool checkServerCapability(const QString & path, shell::ServerCapability capability) override;
    virtual simodo::lsp::ServerCapabilities getServerCapabilities(const QString & path) override;
    virtual simodo::lsp::SimodoCapabilities getSimodoCapabilities(const QString & path) override;
    virtual void didChange(const QString & path, int version) override;
    virtual void hover(const void * sender, const QString & path, int line, int character) override;
    virtual void documentSymbol(const QString & path) override;
    virtual void semanticTokens(const QString & path) override;
    virtual void declaration(const QString & path, int line, int character) override;
    virtual void definition(const QString & path, int line, int character) override;
    virtual void completion(const void * sender, const QString & path, int line, int character, 
                            simodo::lsp::CompletionTriggerKind trigger_kind, 
                            const QString & trigger_character) override;
    virtual void executeSimodoCommand(const QString & path, const QString & command) override;

private slots:
    void publishDiagnostics_notify_slot(QString jsonrpc);
    void hover_result_slot(QString path, QString jsonrpc, const void * sender);
    void documentSymbol_result_slot(QString path, QString jsonrpc);
    void semanticTokens_result_slot(QString path, QString jsonrpc);
    void declaration_definition_result_slot(QString path, QString jsonrpc);
    void completion_result_slot(QString path, QString jsonrpc, const void * sender);
    void simodo_command_result_slot(QString path, QString jsonrpc);

signals:
    void publishDiagnostics_notify_signal(QString jsonrpc);
    void hover_result_signal(QString path, QString jsonrpc, const void * sender);
    void documentSymbol_result_signal(QString path, QString jsonrpc);
    void semanticTokens_result_signal(QString path, QString jsonrpc);
    void declaration_result_signal(QString path, QString jsonrpc);
    void definition_result_signal(QString path, QString jsonrpc);
    void completion_result_signal(QString path, QString jsonrpc, const void * sender);
    void simodo_command_result_signal(QString path, QString jsonrpc);

private:
    bool prepareServer(const QString & path_to_client_setup, bool and_start=false);
};

#endif // LspManagement_H
